package com.gitee.feizns.quickstart.web.spring.boot.autoconfigure;

import com.fasterxml.jackson.databind.JsonDeserializer;
import com.fasterxml.jackson.databind.JsonSerializer;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.module.SimpleModule;
import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule;
import com.gitee.feizns.quickstart.jackson.JsonUtils;
import com.gitee.feizns.quickstart.jackson.QuickstartObjectMapper;
import com.gitee.feizns.quickstart.jackson.module.Java8TimeSerializer;
import lombok.RequiredArgsConstructor;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.boot.autoconfigure.jackson.Jackson2ObjectMapperBuilderCustomizer;
import org.springframework.boot.autoconfigure.jackson.JacksonProperties;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;
import org.springframework.http.converter.json.Jackson2ObjectMapperBuilder;

import java.time.LocalDateTime;
import java.util.List;

/**
 * Spring Mvc JSON序列化配置
 * @link <a href="https://www.jb51.net/article/225008.htm">springboot jackson配置教程</a>
 * @author feizns
 * @since 2019/6/13
 */
@Configuration
@EnableConfigurationProperties({JacksonProperties.class, QuickstartWebProperties.class})
@RequiredArgsConstructor
public class QuickstartJackson2AutoConfiguration {

    /**
     * jackson全局配置
     */
    private final JacksonProperties properties;

    /**
     * Web 属性
     */
    private final QuickstartWebProperties quickstartWebProperties;

    /**
     * 该配置会自动获取spring容器中的所以json序列化和反序列化器
     * @param deserializers {@link JsonDeserializer}
     * @param serializer {@link JsonSerializer}
     * @return {@link Jackson2ObjectMapperBuilderCustomizer}
     */
    @Bean
    public Jackson2ObjectMapperBuilderCustomizer jackson2ObjectMapperBuilderCustomizer(JsonDeserializer<?>[] deserializers, JsonSerializer<?>[] serializer) {
        return jacksonObjectMapperBuilder -> {
            jacksonObjectMapperBuilder.deserializers(deserializers);
            jacksonObjectMapperBuilder.serializers(serializer);
        };
    }

    @Bean
    @Primary
    @ConditionalOnMissingBean
    public ObjectMapper jacksonObjectMapper(Jackson2ObjectMapperBuilder builder, List<SimpleModule> modules) {
        ObjectMapper objectMapper = builder.createXmlMapper(false).build();
        //应用配置
        if ( quickstartWebProperties.isDefaultJacksonConfigEnabled() )
            QuickstartObjectMapper.applyDefaultConfigure(objectMapper);
        //应用spring jackson配置
        applySpringJacksonConfigure(objectMapper);
        //设置工具类的ObjectMapper
        JsonUtils.setObjectMapper(objectMapper);
        //注册所有的 SimpleModule
        modules.forEach(objectMapper::registerModule);
        return objectMapper;
    }

    /**
     * Apply Spring Jackson 配置
     */
    private void applySpringJacksonConfigure(ObjectMapper objectMapper) {
        //设置jackson配置的内容
        if ( properties.getDefaultPropertyInclusion() != null )
            objectMapper.setSerializationInclusion(properties.getDefaultPropertyInclusion());
        if ( properties.getTimeZone() != null )
            objectMapper.setTimeZone(properties.getTimeZone());
    }

    /**
     * java8时间模块
     * @return {@link JavaTimeModule}
     */
    @Bean
    @ConditionalOnMissingBean
    public JavaTimeModule javaTimeModule() {
        JavaTimeModule javaTimeModule = QuickstartObjectMapper.java8TimeModule();
        javaTimeModule.addSerializer(LocalDateTime.class, new Java8TimeSerializer(properties.getDateFormat()));
        return javaTimeModule;
    }

}
